#include "includes.h"
#include "vgs_impl.h"
#include "gal_api.h"
#include "rga_api.h"

static pthread_mutex_t vgs_mutex;
static VGS_JOB_S g_vgs_jobs[VGS_JOB_MAX_NUM] = {0};

int TR_VGS_Module_Init()
{
    memset(g_vgs_jobs, 0L, sizeof(g_vgs_jobs));
    pthread_mutex_init(&vgs_mutex, NULL);

    return TR_SUCCESS;
}

int TR_VGS_Module_DeInit()
{
    memset(g_vgs_jobs, 0L, sizeof(g_vgs_jobs));
    pthread_mutex_destroy(&vgs_mutex);

    return TR_SUCCESS;
}

HI_S32  HI_MPI_VGS_BeginJob(VGS_HANDLE *phHandle)
{
    int i;

    pthread_mutex_lock(&vgs_mutex);

    for (i = 0; i < VGS_JOB_MAX_NUM; i++)
    {
        if (g_vgs_jobs[i].bEnable)
            continue;

        memset(&g_vgs_jobs[i], 0L, sizeof(VGS_JOB_S));
        g_vgs_jobs[i].bEnable = TRUE;
        *phHandle = (VGS_HANDLE)&g_vgs_jobs[i];

        break;
    }

    pthread_mutex_unlock(&vgs_mutex);

    return (i < VGS_JOB_MAX_NUM) ? TR_SUCCESS : TR_FAILURE;
}

//实现1：统一提交给硬件处理，并等待所有操作结束
//实现2: AddTask时就提交给硬件处理，这里只等待所有操作结束
HI_S32 HI_MPI_VGS_EndJob(VGS_HANDLE hHandle)
{
    int i;
    VGS_JOB_S *pstJob;

    pstJob = (VGS_JOB_S *)hHandle;

    //这里暂时直接使用rga
    rga_buffer_t stTmpBuffer;
    rga_buffer_t stSrcBuffer;
    rga_buffer_t stDstBuffer;
    im_rect stSrcRect;
    im_rect stDstRect;
    uint32_t fdSrc,fdDst;
    uint32_t u32Width,u32Height;
    AHardwareBuffer *pstAHBSrc;
    AHardwareBuffer *pstAHBDst;
    
    for (i = 0; i < VGS_TASK_MAX_NUM; i++)
    {
        if (pstJob->tasks[i].bEnable && !pstJob->tasks[i].bCommited)
        {
            if (pstJob->tasks[i].type == VGS_TASK_TYPE_SCALE)
            {
                //pstAHBSrc = (AHardwareBuffer *)TR_MPI_VB_Handle2AHardwareBuffer(pstJob->tasks[i].attr.stImgIn.stVFrame.u64VBHandle);
                //pstAHBDst = (AHardwareBuffer *)TR_MPI_VB_Handle2AHardwareBuffer(pstJob->tasks[i].attr.stImgOut.stVFrame.u64VBHandle);

                if (pstJob->tasks[i].attr.stImgIn.stVFrame.pHardwareBuf != NULL)
                    pstAHBSrc = pstJob->tasks[i].attr.stImgIn.stVFrame.pHardwareBuf;
                else
                    pstAHBSrc = (AHardwareBuffer *)TR_MPI_VB_Handle2AHardwareBuffer(pstJob->tasks[i].attr.stImgIn.stVFrame.u64VBHandle);

                if (pstJob->tasks[i].attr.stImgOut.stVFrame.pHardwareBuf != NULL)
                    pstAHBDst = pstJob->tasks[i].attr.stImgOut.stVFrame.pHardwareBuf;
                else
                    pstAHBDst = (AHardwareBuffer *)TR_MPI_VB_Handle2AHardwareBuffer(pstJob->tasks[i].attr.stImgOut.stVFrame.u64VBHandle);

                stTmpBuffer = wrapbuffer_AHardwareBuffer_c(pstAHBSrc);
                fdSrc = stTmpBuffer.fd;
                stTmpBuffer = wrapbuffer_AHardwareBuffer_c(pstAHBDst);
                fdDst = stTmpBuffer.fd;

                u32Width = pstJob->tasks[i].attr.stImgIn.stVFrame.u32Width;
                u32Height = pstJob->tasks[i].attr.stImgIn.stVFrame.u32Height;
                stSrcRect.x = pstJob->tasks[i].attr.stImgIn.stVFrame.s16OffsetLeft;
                stSrcRect.y = pstJob->tasks[i].attr.stImgIn.stVFrame.s16OffsetTop;;
                stSrcRect.width = pstJob->tasks[i].attr.stImgIn.stVFrame.s16OffsetRight - pstJob->tasks[i].attr.stImgIn.stVFrame.s16OffsetLeft;
                stSrcRect.height = pstJob->tasks[i].attr.stImgIn.stVFrame.s16OffsetBottom - pstJob->tasks[i].attr.stImgIn.stVFrame.s16OffsetTop;
                stSrcBuffer = wrapbuffer_fd_t(fdSrc, u32Width, u32Height, u32Width, u32Height, RK_FORMAT_YCbCr_420_SP);

                u32Width = pstJob->tasks[i].attr.stImgOut.stVFrame.u32Width;
                u32Height = pstJob->tasks[i].attr.stImgOut.stVFrame.u32Height;
                stDstRect.x = pstJob->tasks[i].attr.stImgOut.stVFrame.s16OffsetLeft;
                stDstRect.y = pstJob->tasks[i].attr.stImgOut.stVFrame.s16OffsetTop;;
                stDstRect.width = pstJob->tasks[i].attr.stImgOut.stVFrame.s16OffsetRight - pstJob->tasks[i].attr.stImgOut.stVFrame.s16OffsetLeft;
                stDstRect.height = pstJob->tasks[i].attr.stImgOut.stVFrame.s16OffsetBottom - pstJob->tasks[i].attr.stImgOut.stVFrame.s16OffsetTop;
                stDstBuffer = wrapbuffer_fd_t(fdDst, u32Width, u32Height, u32Width, u32Height, RK_FORMAT_YCbCr_420_SP);

                rga_buffer_t pat;
                im_rect prect = {0,0,0,0};
                int usage = 0;
                IM_STATUS status = improcess(stSrcBuffer, stDstBuffer, pat, stSrcRect, stDstRect, prect, usage);
                if (status != IM_STATUS_SUCCESS)
                {
                    LOG_ERR("improcess error, ret = %d\n", status);
                }

                pstJob->tasks[i].bCommited = TRUE;
            }
        }
    }

    imsync();

    return TR_SUCCESS;
}

HI_S32 HI_MPI_VGS_CancelJob(VGS_HANDLE hHandle)
{
    VGS_JOB_S *pstJob;

    pthread_mutex_lock(&vgs_mutex);

    pstJob = (VGS_JOB_S *)hHandle;
    memset(pstJob, 0L, sizeof(VGS_JOB_S));
    pstJob->bEnable = FALSE;

    pthread_mutex_unlock(&vgs_mutex);

    return TR_SUCCESS;
}

HI_S32  HI_MPI_VGS_AddScaleTask(VGS_HANDLE hHandle, VGS_TASK_ATTR_S *pstTask)
{
    int i;
    VGS_JOB_S *pstJob;
    
    //这里暂时直接使用rga
    rga_buffer_t stTmpBuffer;
    rga_buffer_t stSrcBuffer;
    rga_buffer_t stDstBuffer;
    im_rect stSrcRect;
    im_rect stDstRect;
    uint32_t fdSrc,fdDst;
    uint32_t u32Width,u32Height;
    AHardwareBuffer *pstAHBSrc;
    AHardwareBuffer *pstAHBDst;

    pstJob = (VGS_JOB_S *)hHandle;

    for (i = 0; i < VGS_TASK_MAX_NUM; i++)
    {
        if (!pstJob->tasks[i].bEnable)
        {
            pstJob->tasks[i].bEnable = TRUE;
            pstJob->tasks[i].attr = *pstTask;
            pstJob->tasks[i].type = VGS_TASK_TYPE_SCALE;
            pstJob->tasks[i].bCommited = FALSE;

            if (pstJob->tasks[i].attr.stImgIn.stVFrame.pHardwareBuf != NULL)
                pstAHBSrc = pstJob->tasks[i].attr.stImgIn.stVFrame.pHardwareBuf;
            else
                pstAHBSrc = (AHardwareBuffer *)TR_MPI_VB_Handle2AHardwareBuffer(pstJob->tasks[i].attr.stImgIn.stVFrame.u64VBHandle);

            if (pstJob->tasks[i].attr.stImgOut.stVFrame.pHardwareBuf != NULL)
                pstAHBDst = pstJob->tasks[i].attr.stImgOut.stVFrame.pHardwareBuf;
            else
                pstAHBDst = (AHardwareBuffer *)TR_MPI_VB_Handle2AHardwareBuffer(pstJob->tasks[i].attr.stImgOut.stVFrame.u64VBHandle);

            stTmpBuffer = wrapbuffer_AHardwareBuffer_c(pstAHBSrc);
            fdSrc = stTmpBuffer.fd;
            stTmpBuffer = wrapbuffer_AHardwareBuffer_c(pstAHBDst);
            fdDst = stTmpBuffer.fd;

            u32Width = pstJob->tasks[i].attr.stImgIn.stVFrame.u32Width;
            u32Height = pstJob->tasks[i].attr.stImgIn.stVFrame.u32Height;
            stSrcRect.x = pstJob->tasks[i].attr.stImgIn.stVFrame.s16OffsetLeft;
            stSrcRect.y = pstJob->tasks[i].attr.stImgIn.stVFrame.s16OffsetTop;;
            stSrcRect.width = pstJob->tasks[i].attr.stImgIn.stVFrame.s16OffsetRight - pstJob->tasks[i].attr.stImgIn.stVFrame.s16OffsetLeft;
            stSrcRect.height = pstJob->tasks[i].attr.stImgIn.stVFrame.s16OffsetBottom - pstJob->tasks[i].attr.stImgIn.stVFrame.s16OffsetTop;
            stSrcBuffer = wrapbuffer_fd_t(fdSrc, u32Width, u32Height, u32Width, u32Height, RK_FORMAT_YCbCr_420_SP);

            u32Width = pstJob->tasks[i].attr.stImgOut.stVFrame.u32Width;
            u32Height = pstJob->tasks[i].attr.stImgOut.stVFrame.u32Height;
            stDstRect.x = pstJob->tasks[i].attr.stImgOut.stVFrame.s16OffsetLeft;
            stDstRect.y = pstJob->tasks[i].attr.stImgOut.stVFrame.s16OffsetTop;;
            stDstRect.width = pstJob->tasks[i].attr.stImgOut.stVFrame.s16OffsetRight - pstJob->tasks[i].attr.stImgOut.stVFrame.s16OffsetLeft;
            stDstRect.height = pstJob->tasks[i].attr.stImgOut.stVFrame.s16OffsetBottom - pstJob->tasks[i].attr.stImgOut.stVFrame.s16OffsetTop;
            stDstBuffer = wrapbuffer_fd_t(fdDst, u32Width, u32Height, u32Width, u32Height, RK_FORMAT_YCbCr_420_SP);

            rga_buffer_t pat;
            im_rect prect = {0,0,0,0};
            int usage = 0;
            IM_STATUS status = improcess(stSrcBuffer, stDstBuffer, pat, stSrcRect, stDstRect, prect, usage);
            if (status != IM_STATUS_SUCCESS)
            {
                LOG_ERR("improcess error, ret = %d\n", status);
            }

            pstJob->tasks[i].bCommited = TRUE;
        }
    }

    return TR_SUCCESS;
}

HI_S32 HI_MPI_VGS_AddDrawLineTask(VGS_HANDLE hHandle, VGS_TASK_ATTR_S *pstTask, VGS_LINE_S astVgsDrawLine[], HI_U32 u32ArraySize)
{
    return HI_SUCCESS;
}

HI_S32 HI_MPI_VGS_AddCoverTask(VGS_HANDLE hHandle, VGS_TASK_ATTR_S *pstTask, VGS_COVER_S astVgsAddCover[], HI_U32 u32ArraySize)
{
    return HI_SUCCESS;
}

HI_S32 HI_MPI_VGS_AddOsdTask(VGS_HANDLE hHandle, VGS_TASK_ATTR_S *pstTask, VGS_OSD_S astVgsAddOsd[], HI_U32 u32ArraySize)
{
    return HI_SUCCESS;
}

